import Vue from "vue";
import { request } from "../utils/request";
import { AccessControl } from "./AccessControl";
import MD5 from "md5.js";

const TOKEN = "token";
const RefreshToken = "refreshToken";

export class AppStore {
  /**
   * @type {{
   *   account
   *   nick_name
   *   access_token
   *   refresh_token
   *   expires_in
   * } | null}
   */
  auth = null;

  accessControl = new AccessControl();

  getToken() {
    return sessionStorage.getItem(TOKEN) || localStorage.getItem(TOKEN);
  }

  getRefreshToken() {
    return (
      sessionStorage.getItem(RefreshToken) || localStorage.getItem(RefreshToken)
    );
  }

  canReLogin() {
    return !!this.getRefreshToken();
  }

  cleanTokens() {
    [localStorage, sessionStorage].forEach(api => {
      api.removeItem(TOKEN);
      api.removeItem(RefreshToken);
    });
  }

  setToken(token, refreshToken, keep) {
    keep
      ? localStorage.setItem("keepLogin", keep)
      : localStorage.removeItem("keepLogin");

    const api = keep ? localStorage : sessionStorage;
    api.setItem(TOKEN, token);
    api.setItem(RefreshToken, refreshToken);

    const clearApi = !keep ? localStorage : sessionStorage;
    clearApi.removeItem(TOKEN);
    clearApi.removeItem(RefreshToken);
  }

  async login(form, keep = false) {
    const data = await request("cedar-auth/oauth/token", {
      method: "post",
      params: {
        tenantId: "000000",
        grant_type: "password",
        scope: "all",
        username: form.username,
        password: new MD5().update(form.password).digest("hex")
      }
    });

    this.setToken(data.access_token, data.refresh_token, keep);

    this.auth = data;

    await this.fetchAccessList();

    return data;
  }

  async reLogin() {
    const data = await request("cedar-auth/oauth/token", {
      method: "post",
      params: {
        tenantId: "000000",
        grant_type: "refresh_token",
        scope: "all",
        refresh_token: this.getRefreshToken()
      }
    });

    const keep = !!localStorage.getItem("keepLogin");
    this.setToken(data.access_token, data.refresh_token, keep);

    this.auth = data;

    await this.fetchAccessList();

    return data;
  }

  async fetchAccessList() {
    const { view: list } = await request(
      "cedar-system/enterprisemodulecolumn/getscopecolumn"
    );
    this.accessControl.computedModules(list);
  }
}

export const app = Vue.observable(new AppStore());
